package mobile.util;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import mda.type.IHtmlPage;
import mda.type.comp.OverlayButton;
import mda.type.comp.TimeTableSlot;
import mobile.TidMobile;

import org.joda.time.DateTime;

import flca.mda.api.util.TemplateUtils;
import flca.mda.codegen.data.DataStore;
import flca.mda.codegen.helpers.FileHelper;
import flca.mda.codegen.helpers.StrUtil;

public class MobileUtils {

	public static final int SCREEN_HEIGHT = 500; //TODO
	
	private TemplateUtils tu = new TemplateUtils();
	
	public static String sHomeHRef = "Main.html";
	
	/** 
	 * calculate the ycoord given the total number of buttons/
	 * @param aRank (1-based)
	 * @param aTotal
	 * @return
	 */
	public int[] calcCoords(OverlayButton aBtn, int aRank, int aTotal)
	{
		int result[] = new int[2];
		
		if (aBtn.getXcoord() != null && aBtn.getYcoord() != null) {
			result[0] = aBtn.getXcoord();
			result[1] = aBtn.getYcoord();
		} else {
			int maxY = SCREEN_HEIGHT - 120;
			int rowheight = (maxY - 20) / aTotal; 
		
			result[0] = 20;
			result[1] = 20 + (aRank - 1) * rowheight;
		}
		
		return result;
	}
	
	/**
	 * get the relative url to the given IHtmlPage
	 * @param aPage
	 * @return
	 */
	public String getHref(IHtmlPage aPage)
	{
		Class<?> clz = aPage.getClass();
		String name = clz.getSimpleName();
		String pagePck = tu.getPackage(clz, TidMobile.MOB_TEXT_HTML.name()); //any ITemplate is ok
		
		String thisPck = tu.getPackage(TidMobile.MOB_TEXT_HTML.name());
		if (pagePck.indexOf(thisPck) == 0) {
			pagePck = pagePck.replace(thisPck, "");
		} else {
			pagePck += "/";
		}
		
		if (pagePck.startsWith(".")) {pagePck = pagePck.substring(1);}
		if (!pagePck.endsWith("/")) {pagePck += "/";}
		
		String r = pagePck.replace(".", "/") + name + ".html";
		return r;
	}
	
	public String getHomeHref() 
	{
		String result = sHomeHRef;
		
		String thisPck = tu.getPackage(TidMobile.MOB_TEXT_HTML.name());
		String tokens[] = StrUtil.split(thisPck, ".");
		if (tokens.length > 1){
			for (int i=0; i < tokens.length - 1; i++) {
				result = "../" + result;
			}
		}
			
		return result;
	}
	
	/**
	 * This method will read the given file and return the input.
	 * The filename can be an absolute url, or just a filename. In the later the file will be search in the current model project
	 * @param aFilename
	 * @return
	 */
	public String readText(String aFilename)
	{
		try {
			File f = findFile(aFilename);
			if (f != null) {
				return FileHelper.readFile(f);
			} else {
				throw new FileNotFoundException(aFilename);
			}
		} catch (FileNotFoundException e) {
			return "?? file not found: " + aFilename;
		} catch (IOException e) {
			return "?? io exception reading: " + aFilename + " "  + e;
		}
	}
	
	private File findFile(String aFilename) 
	{
		if (new File(aFilename).exists()) {
			return new File(aFilename);
		} else {
			String modeldir = DataStore.getInstance().getModelProjectDir().getAbsolutePath();
			List<File> files = FileHelper.findFiles(modeldir, new FindFileFilter(aFilename), true);
			if (files.size() > 0) {
				return files.get(0);
			}
		}
		return null;
	}
	
	public String getTimeSlotsHtml(List<TimeTableSlot> aTimeslots)
	{
		StringBuffer sb = new StringBuffer();
		
		List<Integer> days = getTimeSlotDates(aTimeslots);
		List<Integer> locs = getLocations(aTimeslots);
		
		int row = 0; 
		for (Integer day : days ) {
			for (Integer loc : locs) {
				String s = "<div id=^row<%=arg0%>^ style=^float: none^> \n";
				Properties p = props(new Object[] {"" + row++});
				sb.append(subs(s, p));
				for (TimeTableSlot ts : findTimeSlots(aTimeslots, day, loc)) {
					p = props(new Object[] {"" + ts.getStyleId(), ts.getLabel()});
					String s2 = "<div id=^div<%=arg0%>^ style=^float: left^><%=arg1%></div>";
					sb.append(subs(s2, p) + "\n");
				}
				sb.append("<div/> \n");
			}
		}
		
		return sb.toString();
	}

	public Collection<Integer> getTimeSlotsStyleIds(List<TimeTableSlot> aTimeslots)
	{
		Collection<Integer> result = new ArrayList<Integer>();
		
		for (TimeTableSlot ts : aTimeslots) {
			if (!result.contains(ts.getStyleId())) {
				result.add(ts.getStyleId());
			}
		}
		
		return result;
	}

	private Properties props(Object args[]) 
	{
		Properties props = new Properties();
		int i = 0;
		for (Object obj : args) {
			props.put("arg" + i++, obj.toString());
		}
		return props;
	}
	
	private String subs(String aSource, Properties aProps) 
	{
		String result = StrUtil.replace(aSource, "^", "\"");
		result = StrUtil.subsProperties(result, aProps);
		return result;
	}
	
	private List<TimeTableSlot> findTimeSlots(List<TimeTableSlot> aTimeslots, int aDay, int aLoc) 
	{
		List<TimeTableSlot> r = new ArrayList<TimeTableSlot>();
		
		for (TimeTableSlot ts : aTimeslots) {
			Integer day = getTimeslotDay(ts);
			Integer loc = ts.getLocationId();
			if (loc.equals(aLoc) && day.equals(aDay)) {
				r.add(ts);
			}
		}
		
		//todo sort
		return r;
	}
	
//	private static final Calendar now = Calendar.getInstance();

	private List<Integer> getTimeSlotDates(List<TimeTableSlot> aTimeslots)
	{
		List<Integer> days = new ArrayList<Integer>();
		
		for (TimeTableSlot ts : aTimeslots) {
			Integer day = getTimeslotDay(ts);
			if (!days.contains(day)) {
				days.add(day);
			}
		}
		
		Collections.sort(days);
		return days;
	}

	private List<Integer> getLocations(List<TimeTableSlot> aTimeslots)
	{
		List<Integer> locs = new ArrayList<Integer>();
		
		for (TimeTableSlot ts : aTimeslots) {
			Integer loc = new Integer(ts.getLocationId());
			if (!locs.contains(loc)) {
				locs.add(loc);
			}
		}
		
		Collections.sort(locs);
		return locs;
	}

	private Integer getTimeslotDay(TimeTableSlot aTimeslot)
	{
		DateTime dt = new DateTime(aTimeslot.getStartTime());
		return dt.getDayOfYear();
	}
	
	//--------------------------------------------------------
	static class FindFileFilter implements FileFilter
	{
		private String fname;
		
		
		public FindFileFilter(String fname) {
			super();
			this.fname = fname;
		}

		@Override
		public boolean accept(File arg0) 
		{
			return arg0.isDirectory() || arg0.getName().equals(fname);
		}
	}
}
